#include<iostream>
#include<memory>
#include<list>
#include<vector>
#include<unordered_map>
#include<functional>
#include<unistd.h>
#include<cassert>

//定时任务类
using Ontimecallback=std::function<void()>;    //我们不知道任务函数有多少参数，所以void()
using Releasecallback=std::function<void()>;  
class Timer{
    private:
    int _timeout;            //延迟时间（多少秒后执行）
    bool _canceled;          //是否取消    false-任务正常执行    true-任务取消
    uint64_t _timer_id;      //定时器对象id
    Ontimecallback _timer_callback;        //时间到了要执行的函数
    Releasecallback _release_callback;     //清理回调函数
    public:
    Timer(int timeout,uint64_t timer_id)
    :_timeout(timeout),_timer_id(timer_id),_canceled(false)
    {}
    ~Timer(){
        if(_release_callback) _release_callback();   //执行清理回调，处理Timerqueue中的weak_ptr
        if(_timer_callback && !_canceled) _timer_callback();  //确认有任务且任务没有取消，调用这个任务函数
    }
    uint64_t Get_timerid() {return _timer_id;}
    int Get_delaytime() {return _timeout;}
    void canceled() {_canceled=true;}
    void set_timer_callback(const Ontimecallback& cb) {_timer_callback=cb;}
    void set_release_callback(const Releasecallback& cb) {_release_callback=cb;}
};

#define MAX_TIMEOUT 60
class TimerQueue{
    private:
    using Weaktimer=std::weak_ptr<Timer>;
    using Ptrtimer=std::shared_ptr<Timer>;
    using Bucket=std::vector<Ptrtimer>;
    using Bucketlist=std::vector<Bucket>;
    int _tick;
    int _capacity;
    Bucketlist _conns;
    std::unordered_map<uint64_t,Weaktimer> _wheels;
    public:
    TimerQueue():_tick(0),_capacity(MAX_TIMEOUT),_conns(_capacity)
    {}
    bool has_timer(uint64_t id){
        auto it=_wheels.find(id);
        if(it!=_wheels.end()) {return true;}
        return false;
    }
    void add_timer(const Ontimecallback& cb,int delay,uint64_t id){
        if(delay>_capacity || delay<=0 ) return;
        Ptrtimer timer(new Timer(delay,id));
        timer->set_timer_callback(cb);
        timer->set_release_callback(std::bind(&TimerQueue::remove_weaktimer_from_timerqueue,this,id));
        _wheels[id]=Weaktimer(timer);
        _conns[(_tick+delay)%MAX_TIMEOUT].push_back(timer);
    }
    //根据id刷新定时任务
    void timer_refresh(uint64_t id){
        auto it=_wheels.find(id);
        if(it==_wheels.end()){
            std::cout<<"没有这个定时任务, id为:  "<<id<<std::endl;
            return;
        }
        int delay=it->second.lock()->Get_delaytime();
        _conns[(_tick+delay)%MAX_TIMEOUT].push_back(it->second.lock());
    }
    void timer_cancle(uint64_t id){
        auto it=_wheels.find(id);
        assert(it!=_wheels.end());   //添加断言需要在debug下运行使用
        auto ptr=it->second.lock();
        if(ptr) ptr->canceled();
    }
    //清理回调函数，设置给Timer的
    void remove_weaktimer_from_timerqueue(uint64_t id){
        auto it=_wheels.find(id);
        if(it!=_wheels.end()){
            _wheels.erase(it);
        }
    }
    //处理轮子的滚动，执行完这个时间论的任务后轮子要往后移动
    void run_ontime_task(){
        _tick=(_tick+1)%MAX_TIMEOUT;
        _conns[_tick].clear();   //走到一个位置我们就处理这个位置上的所有任务
        //因为我们的定时时间是在Timer对象被析构的时候被触发的，我们这里clear之后，_conns[_tick]中存储的数据类型为vector<Ptrtimer>
        //这里面存储的都是智能指针，在被清理时就会自动销毁从而触发析构，激活定时任务
    }
};

class Timertest{
    private:
    int _data;
    public:
    Timertest(int data):_data(data) {std::cout<<"构造函数"<<std::endl;}
    ~Timertest() {std::cout<<"析构函数"<<std::endl;}
};

void del(Timertest* t){
    delete t;
}

int main()
{
    Timertest* t=new Timertest(10);
    TimerQueue tq;
    uint64_t id=3;    //随便假设一个timer_id
    tq.add_timer(std::bind(&del,t),5,id);
    
    for(int i=0;i<5;i++){
        sleep(1);
        tq.timer_refresh(id);
        std::cout<<"刷新了一下3号任务\n";
        tq.run_ontime_task();
    }
    std::cout<<"刷新任务结束, 5秒后将启动定时任务\n";
    while(1){
        std::cout<<"-------------------------------\n";
        sleep(1);
        tq.run_ontime_task();
        if(tq.has_timer(id)==false){
            std::cout<<"定时任务已完成\n";
            break;
        }
    }
    return 0;
}